/*
 * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved.
 *
 * This software is open source.
 * See the bottom of this file for the licence.
 */

package org.dom4j;

import java.io.IOException;
import java.io.Writer;
import java.util.List;

/**
 * <p> <code>Node</code> defines the polymorphic behavior for all XML nodes in
 * a dom4j tree. </p>
 * 
 * <p> A node can be output as its XML format, can be detached from its position
 * in a document and can have XPath expressions evaluated on itself. </p>
 * 
 * <p> A node may optionally support the parent relationship and may be read
 * only. </p>
 * 
 * @author <a href="mailto:jstrachan@apache.org">James Strachan </a>
 * @version $Revision: 1.2 $
 * 
 * @see #supportsParent
 * @see #isReadOnly
 */
public interface Node extends Cloneable
{
   // W3C DOM complient node type codes

   /** Matches Element nodes */
   short ANY_NODE = 0;

   /** Matches Element nodes */
   short ELEMENT_NODE = 1;

   /** Matches elements nodes */
   short ATTRIBUTE_NODE = 2;

   /** Matches elements nodes */
   short TEXT_NODE = 3;

   /** Matches elements nodes */
   short CDATA_SECTION_NODE = 4;

   /** Matches elements nodes */
   short ENTITY_REFERENCE_NODE = 5;

   /** Matches elements nodes */

   // public static final short ENTITY_NODE = 6;
   /** Matches ProcessingInstruction */
   short PROCESSING_INSTRUCTION_NODE = 7;

   /** Matches Comments nodes */
   short COMMENT_NODE = 8;

   /** Matches Document nodes */
   short DOCUMENT_NODE = 9;

   /** Matches DocumentType nodes */
   short DOCUMENT_TYPE_NODE = 10;

   // public static final short DOCUMENT_FRAGMENT_NODE = 11;
   // public static final short NOTATION_NODE = 12;

   /** Matchs a Namespace Node - NOTE this differs from DOM */

   // XXXX: ????
   short NAMESPACE_NODE = 13;

   /** Does not match any valid node */
   short UNKNOWN_NODE = 14;

   /** The maximum number of node types for sizing purposes */
   short MAX_NODE_TYPE = 14;

   /**
    * <p> <code>supportsParent</code> returns true if this node supports the
    * parent relationship. </p>
    * 
    * <p> Some XML tree implementations are singly linked and only support
    * downward navigation through children relationships. The default case is
    * that both parent and children relationships are supported though for
    * memory and performance reasons the parent relationship may not be
    * supported. </p>
    * 
    * @return true if this node supports the parent relationship or false it is
    *         not supported
    */
   boolean supportsParent();

   /**
    * <p> <code>getParent</code> returns the parent <code>Element</code> if
    * this node supports the parent relationship or null if it is the root
    * element or does not support the parent relationship. </p>
    * 
    * <p> This method is an optional feature and may not be supported for all
    * <code>Node</code> implementations. </p>
    * 
    * @return the parent of this node or null if it is the root of the tree or
    *         the parent relationship is not supported.
    */
   Element getParent();

   /**
    * <p> <code>setParent</code> sets the parent relationship of this node if
    * the parent relationship is supported or does nothing if the parent
    * relationship is not supported. </p>
    * 
    * <p> This method should only be called from inside an <code>Element</code>
    * implementation method and is not intended for general use. </p>
    * 
    * @param parent is the new parent of this node.
    */
   void setParent(Element parent);

   /**
    * <p> <code>getDocument</code> returns the <code>Document</code> that
    * this <code>Node</code> is part of if this node supports the parent
    * relationship. </p>
    * 
    * <p> This method is an optional feature and may not be supported for all
    * <code>Node</code> implementations. </p>
    * 
    * @return the document of this node or null if this feature is not supported
    *         or the node is not associated with a <code>Document</code>
    */
   Document getDocument();

   /**
    * <p> <code>setDocument</code> sets the document of this node if the
    * parent relationship is supported or does nothing if the parent
    * relationship is not supported. </p>
    * 
    * <p> This method should only be called from inside a <code>Document</code>
    * implementation method and is not intended for general use. </p>
    * 
    * @param document is the new document of this node.
    */
   void setDocument(Document document);

   /**
    * <p> <code>isReadOnly</code> returns true if this node is read only and
    * cannot be modified. Any attempt to modify a read-only <code>Node</code>
    * will result in an <code>UnsupportedOperationException</code> being
    * thrown. </p>
    * 
    * @return true if this <code>Node</code> is read only and cannot be
    *         modified otherwise false.
    */
   boolean isReadOnly();

   /**
    * <p> <code>hasContent</code> returns true if this node is a Branch
    * (either an Element or a Document) and it contains at least one content
    * node such as a child Element or Text node. </p>
    * 
    * @return true if this <code>Node</code> is a Branch with a nodeCount() of
    *         one or more.
    */
   boolean hasContent();

   /**
    * <p> <code>getName</code> returns the name of this node. This is the XML
    * local name of the element, attribute, entity or processing instruction.
    * For CDATA and Text nodes this method will return null. </p>
    * 
    * @return the XML name of this node
    */
   String getName();

   /**
    * <p> Sets the text data of this node or this method will throw an
    * <code>UnsupportedOperationException</code> if it is read-only. </p>
    * 
    * @param name is the new name of this node
    */
   void setName(String name);

   /**
    * <p> Returns the text of this node. </p>
    * 
    * @return the text for this node.
    */
   String getText();

   /**
    * <p> Sets the text data of this node or this method will throw an
    * <code>UnsupportedOperationException</code> if it is read-only. </p>
    * 
    * @param text is the new textual value of this node
    */
   void setText(String text);

   /**
    * Returns the XPath string-value of this node. The behaviour of this method
    * is defined in the <a href="http://www.w3.org/TR/xpath">XPath specification
    * </a>.
    * 
    * @return the text from all the child Text and Element nodes appended
    *         together.
    */
   String getStringValue();

   /**
    * <p> Returns the XPath expression which will return a node set containing
    * the given node such as /a/b/&#64;c. No indexing will be used to restrict
    * the path if multiple elements with the same name occur on the path. </p>
    * 
    * @return the XPath expression which will return a nodeset containing at
    *         least this node.
    */
   String getPath();

   /**
    * Returns the relative XPath expression which will return a node set
    * containing the given node such as a/b/&#64;c. No indexing will be used to
    * restrict the path if multiple elements with the same name occur on the
    * path.
    * 
    * @param context is the parent context from which the relative path should
    *           start. If the context is null or the context is not an ancestor
    *           of this node then the path will be absolute and start from the
    *           document and so begin with the '/' character.
    * 
    * @return the XPath expression relative to the given context which will
    *         return a nodeset containing at least this node.
    */
   String getPath(Element context);

   /**
    * <p> Returns the XPath expression which will return a nodeset of one node
    * which is the current node. This method will use the XPath index operator
    * to restrict the path if multiple elements with the same name occur on the
    * path. </p>
    * 
    * @return the XPath expression which will return a nodeset containing just
    *         this node.
    */
   String getUniquePath();

   /**
    * <p> Returns the relative unique XPath expression from the given context
    * which will return a nodeset of one node which is the current node. This
    * method will use the XPath index operator to restrict the path if multiple
    * elements with the same name occur on the path. </p>
    * 
    * @param context is the parent context from which the path should start. If
    *           the context is null or the context is not an ancestor of this
    *           node then the path will start from the document and so begin
    *           with the '/' character.
    * 
    * @return the XPath expression relative to the given context which will
    *         return a nodeset containing just this node.
    */
   String getUniquePath(Element context);

   /**
    * <p> <code>asXML</code> returns the textual XML representation of this
    * node. </p>
    * 
    * @return the XML representation of this node
    */
   String asXML();

   /**
    * <p> <code>write</code> writes this node as the default XML notation for
    * this node. If you wish to control the XML output (such as for pretty
    * printing, changing the indentation policy etc.) then please use {@link
    * org.dom4j.io.XMLWriter} or its derivations. </p>
    * 
    * @param writer is the <code>Writer</code> to output the XML to
    * 
    * @throws IOException DOCUMENT ME!
    */
   void write(Writer writer) throws IOException;

   /**
    * Returns the code according to the type of node. This makes processing
    * nodes polymorphically much easier as the switch statement can be used
    * instead of multiple if (instanceof) statements.
    * 
    * @return a W3C DOM complient code for the node type such as ELEMENT_NODE or
    *         ATTRIBUTE_NODE
    */
   short getNodeType();

   /**
    * DOCUMENT ME!
    * 
    * @return the name of the type of node such as "Document", "Element",
    *         "Attribute" or "Text"
    */
   String getNodeTypeName();

   /**
    * <p> Removes this node from its parent if there is one. If this node is the
    * root element of a document then it is removed from the document as well.
    * </p>
    * 
    * <p> This method is useful if you want to remove a node from its source
    * document and add it to another document. For example </p>
    * <code> Node node = ...; Element someOtherElement = ...;
    * someOtherElement.add( node.detach() ); </code>
    * 
    * @return the node that has been removed from its parent node if any and its
    *         document if any.
    */
   Node detach();

   /**
    * <p> <code>selectNodes</code> evaluates an XPath expression and returns
    * the result as a <code>List</code> of <code>Node</code> instances or
    * <code>String</code> instances depending on the XPath expression. </p>
    * 
    * @param xpathExpression is the XPath expression to be evaluated
    * 
    * @return the list of <code>Node</code> or <code>String</code> instances
    *         depending on the XPath expression
    */
   List selectNodes(String xpathExpression);

   /**
    * <p> <code>selectObject</code> evaluates an XPath expression and returns
    * the result as an {@link Object}. The object returned can either be a
    * {@link List} of one or more {@link Node}instances or a scalar object like
    * a {@link String}or a {@link Number}instance depending on the XPath
    * expression. </p>
    * 
    * @param xpathExpression is the XPath expression to be evaluated
    * 
    * @return the value of the XPath expression as a {@link List}of {@link
    *         Node} instances, a {@link String}or a {@link Number}instance
    *         depending on the XPath expression.
    */
   Object selectObject(String xpathExpression);

   /**
    * <p> <code>selectNodes</code> evaluates an XPath expression then sorts
    * the results using a secondary XPath expression Returns a sorted
    * <code>List</code> of <code>Node</code> instances. </p>
    * 
    * @param xpathExpression is the XPath expression to be evaluated
    * @param comparisonXPathExpression is the XPath expression used to compare
    *           the results by for sorting
    * 
    * @return the list of <code>Node</code> instances sorted by the
    *         comparisonXPathExpression
    */
   List selectNodes(String xpathExpression, String comparisonXPathExpression);

   /**
    * <p> <code>selectNodes</code> evaluates an XPath expression then sorts
    * the results using a secondary XPath expression Returns a sorted
    * <code>List</code> of <code>Node</code> instances. </p>
    * 
    * @param xpathExpression is the XPath expression to be evaluated
    * @param comparisonXPathExpression is the XPath expression used to compare
    *           the results by for sorting
    * @param removeDuplicates if this parameter is true then duplicate values
    *           (using the comparisonXPathExpression) are removed from the
    *           result List.
    * 
    * @return the list of <code>Node</code> instances sorted by the
    *         comparisonXPathExpression
    */
   List selectNodes(String xpathExpression, String comparisonXPathExpression,
      boolean removeDuplicates);

   /**
    * <p> <code>selectSingleNode</code> evaluates an XPath expression and
    * returns the result as a single <code>Node</code> instance. </p>
    * 
    * @param xpathExpression is the XPath expression to be evaluated
    * 
    * @return the <code>Node</code> matching the XPath expression
    */
   Node selectSingleNode(String xpathExpression);

   /**
    * <p> <code>valueOf</code> evaluates an XPath expression and returns the
    * textual representation of the results the XPath string-value of this node.
    * The string-value for a given node type is defined in the <a
    * href="http://www.w3.org/TR/xpath">XPath specification </a>. </p>
    * 
    * @param xpathExpression is the XPath expression to be evaluated
    * 
    * @return the string-value representation of the results of the XPath
    *         expression
    */
   String valueOf(String xpathExpression);

   /**
    * <p> <code>numberValueOf</code> evaluates an XPath expression and returns
    * the numeric value of the XPath expression if the XPath expression results
    * in a number, or null if the result is not a number. </p>
    * 
    * @param xpathExpression is the XPath expression to be evaluated
    * 
    * @return the numeric result of the XPath expression or null if the result
    *         is not a number.
    */
   Number numberValueOf(String xpathExpression);

   /**
    * <p> <code>matches</code> returns true if evaluating the given XPath
    * expression on this node returns a non-empty node set containing this node.
    * </p>
    * 
    * <p> This method does not behave like the &lt;xsl:if&gt; element - if you
    * want that behaviour, to evaluate if an XPath expression matches something,
    * then you can use the following code to be equivalent... </p>
    * <code>if ( node.selectSingleNode( "/some/path" ) != nulll )</code>
    * 
    * @param xpathExpression is an XPath expression
    * 
    * @return true if this node is returned by the given XPath expression
    */
   boolean matches(String xpathExpression);

   /**
    * <p> <code>createXPath</code> creates an XPath object for the given
    * xpathExpression. The XPath object allows the variable context to be
    * specified. </p>
    * 
    * @param xpathExpression is the XPath expression to be evaluated
    * 
    * @return an XPath object represeting the given expression
    * 
    * @throws InvalidXPathException if the XPath expression is invalid
    */
   XPath createXPath(String xpathExpression) throws InvalidXPathException;

   /**
    * <p> <code>asXPathResult</code> returns a version of this node which is
    * capable of being an XPath result. The result of an XPath expression should
    * always support the parent relationship, whether the original XML tree was
    * singly or doubly linked. If the node does not support the parent
    * relationship then a new node will be created which is linked to its parent
    * and returned. </p>
    * 
    * @param parent DOCUMENT ME!
    * 
    * @return a <code>Node</code> which supports the parent relationship
    */
   Node asXPathResult(Element parent);

   /**
    * <p> <code>accept</code> is the method used in the Visitor Pattern. </p>
    * 
    * @param visitor is the visitor in the Visitor Pattern
    */
   void accept(Visitor visitor);

   /**
    * <p> <code>clone</code> will return a deep clone or if this node is
    * read-only then clone will return the same instance. </p>
    * 
    * @return a deep clone of myself or myself if I am read only.
    */
   Object clone();
}

/*
 * Redistribution and use of this software and associated documentation
 * ("Software"), with or without modification, are permitted provided that the
 * following conditions are met:
 * 
 * 1. Redistributions of source code must retain copyright statements and
 * notices. Redistributions must also contain a copy of this document.
 * 
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 * 
 * 3. The name "DOM4J" must not be used to endorse or promote products derived
 * from this Software without prior written permission of MetaStuff, Ltd. For
 * written permission, please contact dom4j-info@metastuff.com.
 * 
 * 4. Products derived from this Software may not be called "DOM4J" nor may
 * "DOM4J" appear in their names without prior written permission of MetaStuff,
 * Ltd. DOM4J is a registered trademark of MetaStuff, Ltd.
 * 
 * 5. Due credit should be given to the DOM4J Project - http://www.dom4j.org
 * 
 * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL METASTUFF, LTD. OR ITS CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 * 
 * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved.
 */
